#include <iostream>
#include <memory>

class VItem {
    public:
        VItem() {}

        virtual ~VItem() {
            std::cout << "[  VItem  ] destroyed." << std::endl;
        }

};

typedef struct item_s {
    int data;
    int val;

    item_s(int val, int data) {
        this->val = val;
        this->data = data;
        std::cout << "[  item  ] initialized. val: " << this->val << std::endl;
    }

    ~item_s() {
        std::cout << "[  item  ] destroyed." << std::endl;
    }
} item_t;


typedef struct entity_s {
    std::shared_ptr<item_t> item;
    std::shared_ptr<VItem> vitem;

    entity_s(int val, int data) {
        this->item = std::make_shared<item_t>(val, data);
        this->vitem = std::make_shared<VItem>();
        std::cout << "[ entity ] initialized. val: " << item->val << ", data: " << item->data << std::endl;
    }

    ~entity_s() {
        std::cout << "[ entity ] destroyed." << std::endl;
    }
} entity_t;


std::shared_ptr<entity_t> make() {
    std::shared_ptr<entity_t> entity = std::make_shared<entity_t>(10, 256);
    return entity;
}


void test(std::shared_ptr<entity_t> entity) {
    std::cout << "[  test  ] current val: " << entity->item->val << " and refs: " << entity.use_count() << std::endl;
}


int main() {
    //entity_t *entity = new entity_t;
    std::shared_ptr<entity_t> entity = make();

    std::cout << "[  main  ] prepare enter func:test. >>>> entity: " << entity << " and refs: " << entity.use_count() << std::endl;
    test(entity);
    //test(p_entity);
    std::cout << "[  main  ] after func:test. current val: " << entity->item->val << " <<<< entity: " << entity << std::endl;

    //entity = nullptr;
    std::cout << "[  main  ] finished." << std::endl;

    return 0;
}
